package net.tv90.bfmccore.squad;

import net.tv90.bfmccore.game.view.GameModelViewHandler;
import net.tv90.bfmccore.util.Cooldown;
import net.tv90.bfmccore.util.TempPermission;
import org.bitterorange.flansmodslain.FlansModAPI;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;

import java.util.*;

import static net.tv90.bfmccore.game.GameManager.inBattleFieldPlayers;
import static net.tv90.bfmccore.helper.FactionHelper.getCountry2;
import static net.tv90.bfmccore.slot.SlotHelper.giveSlot;
import static net.tv90.bfmccore.util.Ribbon.addNumberForRibbon;

public class Squad {
    public static final String[] factionList = {"RU", "US", "CN"};
    /**
     * 存储队伍名称的翻译
     */
    public static final Map<String, String> squadMap_Lang = new HashMap<>();
    /**
     * 存储小队成员 K = 阵营(RU/CN/US_Squad_0/1/2/3/4/5) V = 小队内玩家列表
     * K的数量应该为3阵营x6小队 = 18，V的数量应该为5(每个小队人数上限为5)
     */
    public static Map<String, LinkedList<String>> squadMap = new HashMap<>();
    /**
     * 存储玩家所在队伍，方便索引 K = 玩家名称 V = 玩家所在队伍名称(RU_Squad_0)
     */
    public static Map<String, String> playerSquadCache = new HashMap<>();
    /**
     * 受到邀请的玩家都会储存在这个集合中 K = 被邀请者 V = 邀请者
     */
    public static Map<String, String> playerInviteMap = new HashMap<>();
    /**
     * 被邀请者都会储存在这个集合中，用于缓存
     */
    public static List<String> playerInviteeCache = new ArrayList<>();

    public static int SQUAD_MAX_SIZE = 10;

    static {
        for (String faction : factionList) {
            squadMap_Lang.put(faction + "_Squad_0", "ALPHA");
            squadMap_Lang.put(faction + "_Squad_1", "BRAVO");
            squadMap_Lang.put(faction + "_Squad_2", "CHARLIE");
            squadMap_Lang.put(faction + "_Squad_3", "DELTA");
            squadMap_Lang.put(faction + "_Squad_4", "ECHO");
            squadMap_Lang.put(faction + "_Squad_5", "FOXTROT");
        }
    }

    /**
     * 初始化队伍信息Map
     */
    public static void initSquadMap() {
        if (!squadMap.isEmpty()) return;
        for (String faction : factionList) {
            for (int i = 0; i <= 5; i++) {
                squadMap.put(faction + "_Squad_" + i, new LinkedList<>());
            }
        }
    }

    /**
     * 清除所有队伍信息
     */
    public static void clearSquadMap() {
        Bukkit.getOnlinePlayers().forEach(p -> {
            TempPermission.unsetTempPerm(p, "bfmc.squadleader");
        });
        playerSquadCache.clear();
        squadMap.clear();
        playerInviteeCache.clear();
        playerInviteMap.clear();
        initSquadMap();
    }

    /**
     * 玩家加入小队
     *
     * @param p     玩家
     * @param index 小队编号索引 0~5
     * @return 是否加入成功
     */
    public static synchronized boolean join(Player p, int index) {
        if (index == -1) return false;
        //获取玩家及小队信息
        String faction = getCountry2(p);
        LinkedList<String> list = squadMap.get(faction + "_Squad_" + index);
        String squadName = squadMap_Lang.get(faction + "_Squad_" + index);
        if (list.size() == SQUAD_MAX_SIZE) {
            GameModelViewHandler.getInstance().createSquadJoinInfoGui(p, squadName + "小队已满[" + SQUAD_MAX_SIZE + "/" + SQUAD_MAX_SIZE + "]");
            p.sendMessage("§a[队伍]" + squadName + "小队已满[" + SQUAD_MAX_SIZE + "/" + SQUAD_MAX_SIZE + "]");
            return false;
        }
        //检测玩家是否已经在当前小队
        if (list.contains(p.getName())) {
            GameModelViewHandler.getInstance().createInfoGui(p, "你已经在" + squadName + "小队中", GameModelViewHandler.getInstance()::createMainGUI);
            p.sendMessage("§a[队伍]你已经在" + squadName + "小队中");
            return false;
        }
        //检测玩家是否已经在其他小队内，若已在小队内，先退出当前小队，再加入其他小队
        String currentSquad = playerSquadCache.getOrDefault(p.getName(), "No Squad");
        quit(p, currentSquad);
        //通告队员有新人加入小队
        for (String str : list) {
            Player teamer = Bukkit.getPlayerExact(str);
            if (teamer == null) {
                list.remove(str);
            } else {
                teamer.sendMessage("§a[队伍]玩家" + p.getName() + "加入了你的小队");
            }
        }
        //将玩家加入小队Map
        list.addLast(p.getName());
        playerSquadCache.put(p.getName(), faction + "_Squad_" + index);
        squadMap.put(faction + "_Squad_" + index, list);
        p.sendMessage("§a[队伍]你已经加入了" + squadName + "小队");
        //如果只有一名玩家，将玩家设为小队长
        if (list.get(0).equals(p.getName())) {
            TempPermission.setTempPerm(p, "bfmc.squadleader");
        }
        return true;
    }

    /**
     * 随机加入小队
     *
     * @param p 玩家
     */
    public static synchronized void joinRandom(Player p) {
        //随机生成0~5的数字索引
        int index = new Random().nextInt(6);
        join(p, index);
    }

    /**
     * 自动按顺序加入小队
     *
     * @param p 玩家
     */
    public static void autoJoin(Player p) {
        for (int index = 0; index <= 5; index++) {
            if (join(p, index)) return;
        }
    }

    /**
     * 获取玩家当前的小队编号
     *
     * @param p 玩家
     * @return 小队编号 0~5 如果不存在返回-1
     */
    public static int getSquadIndex(Player p) {
        if (!playerSquadCache.containsKey(p.getName())) {
            return -1;
        }
        String value = playerSquadCache.get(p.getName());
        String[] str = value.split("_");
        return Integer.parseInt(str[2]);
    }

    public static int getSquadIndex(String pName) {
        if (!playerSquadCache.containsKey(pName)) {
            return -1;
        }
        String value = playerSquadCache.get(pName);
        String[] str = value.split("_");
        return Integer.parseInt(str[2]);
    }

    /**
     * 获取玩家的阵营名称
     *
     * @param p 玩家
     * @return 阵营名称 ALPHA 若不存在返回 “No Squad”
     */
    public static String getSquad(Player p) {
        if (!playerSquadCache.containsKey(p.getName())) {
            return "No Squad";
        }
        return squadMap_Lang.get(playerSquadCache.get(p.getName()));
    }

    /**
     * 玩家退出小队
     *
     * @param p 玩家
     */
    public static synchronized void quit(Player p) {
        int index = getSquadIndex(p);
        if (index == -1) {
            GameModelViewHandler.getInstance().createSquadJoinInfoGui(p, "你当前不在任何一个小队中");
            p.sendMessage("§a[队伍]你当前不在任何一个小队中");
            return;
        }
        playerSquadCache.remove(p.getName());
        String faction = getCountry2(p);
        LinkedList<String> list = squadMap.get(faction + "_Squad_" + index);
        String squadName = squadMap_Lang.get(faction + "_Squad_" + index);
        //如果退出的玩家是小队长，取消玩家的小队长权限，并通告新任小队长
        if (p.getName().equals(list.get(0))) {
            TempPermission.unsetTempPerm(p, "bfmc.squadleader");
            if (list.size() > 1) {
                Player leader = Bukkit.getPlayerExact(list.get(1));
                leader.sendMessage("§a[队伍]你成为当前小队的队长");
                TempPermission.setTempPerm(leader, "bfmc.squadleader");
            }
        }
        //将玩家移出小队
        list.remove(p.getName());
        //通告剩下的队员有玩家退出小队
        if (list.size() > 0) {
            for (String str : list) {
                Player teamer = Bukkit.getPlayerExact(str);
                if (teamer == null) {
                    list.remove(str);
                } else {
                    teamer.sendMessage("§a[队伍]玩家" + p.getName() + "退出了你的小队");
                }
            }
        }
        squadMap.put(faction + "_Squad_" + index, list);
        p.sendMessage("§a[队伍]你已经退出了" + squadName + "小队");
    }

    public static void quit(String pName, String faction) {
        int index = getSquadIndex(pName);
        if (index == -1) {
            return;
        }
        playerSquadCache.remove(pName);
        LinkedList<String> list = squadMap.get(faction + "_Squad_" + index);
        String squadName = squadMap_Lang.get(faction + "_Squad_" + index);
        //如果退出的玩家是小队长，取消玩家的小队长权限，并通告新任小队长
        if (pName.equals(list.get(0))) {
            if (list.size() > 1) {
                Player leader = Bukkit.getPlayerExact(list.get(1));
                leader.sendMessage("§a[队伍]你成为当前小队的队长");
                TempPermission.setTempPerm(leader, "bfmc.squadleader");
            }
        }
        //将玩家移出小队
        list.remove(pName);
        //通告剩下的队员有玩家退出小队
        if (list.size() > 0) {
            for (String str : list) {
                Player teamer = Bukkit.getPlayerExact(str);
                if (teamer == null) {
                    list.remove(str);
                } else {
                    teamer.sendMessage("§a[队伍]玩家" + pName + "退出了你的小队");
                }
            }
        }
        squadMap.put(faction + "_Squad_" + index, list);
    }

    /**
     * 将玩家退出小队(该玩家不会收到提示)
     *
     * @param p         玩家
     * @param squadName 小队名称
     */
    public static synchronized void quit(Player p, String squadName) {
        if (!squadName.equals("No Squad")) {
            playerSquadCache.remove(p.getName());
            LinkedList<String> list = squadMap.get(squadName);
            //如果退出的玩家是小队长，取消玩家的小队长权限，并通告新任小队长
            if (p.getName() == null || p.getName().equals(list.get(0))) {
                TempPermission.unsetTempPerm(p, "bfmc.squadleader");
                //Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "lp user " + p.getName() + " permission unset bfmc.squadleader");
                if (list.size() > 1) {
                    Player leader = Bukkit.getPlayerExact(list.get(1));
                    leader.sendMessage("§a[队伍]你成为当前小队的队长");
                    TempPermission.setTempPerm(p, "bfmc.squadleader");
                    //Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "lp user " + list.get(1) + " permission set bfmc.squadleader true");
                }
            }
            list.remove(p.getName());
            //通告剩下的队员有玩家退出小队
            if (list.size() > 0) {
                for (String str : list) {
                    Player teamer = Bukkit.getPlayerExact(str);
                    teamer.sendMessage("§a[队伍]玩家" + p.getName() + "退出了你的小队");
                }
            }
            squadMap.put(squadName, list);
        }
    }

    /**
     * 获取一个玩家所在的小队成员列表
     *
     * @param p 玩家
     * @return 小队成员列表
     */
    public static List<String> getSquadMember(Player p) {
        return squadMap.getOrDefault(playerSquadCache.get(p.getName()), null);
    }

    /**
     * 根据小队名获取小队成员
     *
     * @param squadName 小队名
     * @return 小队成员列表
     */
    public static List<String> getSquadMember(String squadName) {
        return squadMap.get(squadName);
    }

    /**
     * 获取一个玩家所在小队的队长
     *
     * @param p 玩家
     */
    public static String getLeader(Player p) {
        if (getSquadMember(p) != null && !getSquadMember(p).isEmpty()) {
            return getSquadMember(p).get(0);
        }
        return "No Leader";
    }

    /**
     * 将玩家传送到小队长的位置
     *
     * @param p 玩家
     */
    public static void teleportToLeader(Player p) {
        try {
            if (getLeader(p).equals("No Leader")) {
                p.sendMessage("§a[队伍]你当前不在任何一个小队中");
                GameModelViewHandler.getInstance().createSquadJoinInfoGui(p, "你当前不在任何一个小队中");
                return;
            }
            Player leader = Bukkit.getPlayerExact(getLeader(p));
            if (leader.getUniqueId().equals(p.getUniqueId())) {
                p.sendMessage("§a[队伍]你已经是队伍的小队长，不能传送到自己");
                GameModelViewHandler.getInstance().createInfoGui(p, "你已经是队伍的小队长，不能传送到自己", GameModelViewHandler.getInstance()::createMainGUI);
                return;
            }
            if (leader.getHealth() == 0 || !inBattleFieldPlayers.contains(leader)) {
                p.sendMessage("§a[队伍]小队长已死亡，无法传送");
                GameModelViewHandler.getInstance().createInfoGui(p, "小队长已死亡，无法传送", GameModelViewHandler.getInstance()::createMainGUI);
                return;
            }
//            if (leader.isSneaking()) {
//                p.sendMessage("§a[队伍]小队长在战斗中，无法传送");
//                GameModelViewHandler.getInstance().createInfoGui(p,"小队长在战斗中，无法传送", GameModelViewHandler.getInstance()::createMainGUI);
//                return;
//            }
            if (Cooldown.isCool("Teleport", p)) {
                p.sendMessage("§a[队伍]传送冷却时间剩余" + Cooldown.getTime("Teleport", p) + "秒");
                return;
            }
            Location loc = leader.getLocation();

            if(leader.getVehicle() != null && FlansModAPI.isMCHeliAircraft(leader.getVehicle())) {
                if(!FlansModAPI.mountFirstEmptySeat(p, leader.getVehicle())) {
                    GameModelViewHandler.getInstance().createInfoGui(p, "小队长载具已满", GameModelViewHandler.getInstance()::createMainGUI);
                    return;
                }
            } else {
                p.teleport(loc);
            }
            p.closeInventory();
            p.sendMessage("§a[队伍]已传送至小队长" + leader.getName());
            p.playSound(p.getLocation(), "custom.Deploy", 20.0F, 1.0F);
            inBattleFieldPlayers.add(p);
            try {
                giveSlot(p);
            } catch (Exception e) {
                e.printStackTrace();
            }
            leader.sendMessage("§a[队伍]队员" + p.getName() + "已传送至你的位置");
            addNumberForRibbon(leader, "SquadDeploy", "小队部署", 10);
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 邀请某玩家加入小队
     *
     * @param sender  邀请发送者
     * @param invitee 被邀请者
     */
    public static void invite(Player sender, Player invitee) {
        if (invitee == null || sender == null) {
            return;
        }
        String senderSquad = getSquad(sender);
        if (senderSquad.equals("No Squad")) {
            sender.sendMessage("§a[队伍]你当前不在任何一个小队中");
            return;
        }
        if (!getCountry2(sender).equals(getCountry2(invitee))) {
            sender.sendMessage("§a[队伍]不能邀请其他阵营的玩家加入小队");
            return;
        }
        if (getSquadIndex(sender) == getSquadIndex(invitee)) {
            sender.sendMessage("§a[队伍]该玩家已经在你的小队中");
            return;
        }
        sender.sendMessage("§a[队伍]已邀请玩家" + invitee.getName() + "加入你的小队");
        invitee.sendMessage("§a[队伍]玩家" + sender.getName() + "邀请你加入" + senderSquad + "小队,可用Q键快捷语音同意或拒绝该邀请");
        if (!playerInviteeCache.contains(invitee.getName())) playerInviteeCache.add(invitee.getName());
        playerInviteMap.put(invitee.getName(), sender.getName());
    }
}
